1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.google.common.collect;
18
19 import com.google.common.annotations.GwtCompatible;
20 import com.google.common.annotations.GwtIncompatible;
21 import com.google.common.testing.GcFinalization;
22
23 import junit.framework.TestCase;
24
25 import java.lang.ref.WeakReference;
26 import java.util.Iterator;
27 import java.util.NoSuchElementException;
28
29
30
31
32
33
34 @SuppressWarnings("serial")
35 @GwtCompatible(emulated = true)
36
37 public class AbstractIteratorTest extends TestCase {
38
39 public void testDefaultBehaviorOfNextAndHasNext() {
40
41
42
43 Iterator<Integer> iter = new AbstractIterator<Integer>() {
44 private int rep;
45 @Override public Integer computeNext() {
46 switch (rep++) {
47 case 0:
48 return 0;
49 case 1:
50 return 1;
51 case 2:
52 return endOfData();
53 default:
54 fail("Should not have been invoked again");
55 return null;
56 }
57 }
58 };
59
60 assertTrue(iter.hasNext());
61 assertEquals(0, (int) iter.next());
62
63
64 assertTrue(iter.hasNext());
65 assertTrue(iter.hasNext());
66 assertTrue(iter.hasNext());
67 assertEquals(1, (int) iter.next());
68
69 assertFalse(iter.hasNext());
70
71
72 assertFalse(iter.hasNext());
73
74 try {
75 iter.next();
76 fail("no exception thrown");
77 } catch (NoSuchElementException expected) {
78 }
79 }
80
81 public void testDefaultBehaviorOfPeek() {
82
83
84
85
86 AbstractIterator<Integer> iter = new AbstractIterator<Integer>() {
87 private int rep;
88 @Override public Integer computeNext() {
89 switch (rep++) {
90 case 0:
91 return 0;
92 case 1:
93 return 1;
94 case 2:
95 return endOfData();
96 default:
97 fail("Should not have been invoked again");
98 return null;
99 }
100 }
101 };
102
103 assertEquals(0, (int) iter.peek());
104 assertEquals(0, (int) iter.peek());
105 assertTrue(iter.hasNext());
106 assertEquals(0, (int) iter.peek());
107 assertEquals(0, (int) iter.next());
108
109 assertEquals(1, (int) iter.peek());
110 assertEquals(1, (int) iter.next());
111
112 try {
113 iter.peek();
114 fail("peek() should throw NoSuchElementException at end");
115 } catch (NoSuchElementException expected) {
116 }
117
118 try {
119 iter.peek();
120 fail("peek() should continue to throw NoSuchElementException at end");
121 } catch (NoSuchElementException expected) {
122 }
123
124 try {
125 iter.next();
126 fail("next() should throw NoSuchElementException as usual");
127 } catch (NoSuchElementException expected) {
128 }
129
130 try {
131 iter.peek();
132 fail("peek() should still throw NoSuchElementException after next()");
133 } catch (NoSuchElementException expected) {
134 }
135 }
136
137 @GwtIncompatible("weak references")
138 public void testFreesNextReference() {
139 Iterator<Object> itr = new AbstractIterator<Object>() {
140 @Override public Object computeNext() {
141 return new Object();
142 }
143 };
144 WeakReference<Object> ref = new WeakReference<Object>(itr.next());
145 GcFinalization.awaitClear(ref);
146 }
147
148 public void testDefaultBehaviorOfPeekForEmptyIteration() {
149
150 AbstractIterator<Integer> empty = new AbstractIterator<Integer>() {
151 private boolean alreadyCalledEndOfData;
152 @Override public Integer computeNext() {
153 if (alreadyCalledEndOfData) {
154 fail("Should not have been invoked again");
155 }
156 alreadyCalledEndOfData = true;
157 return endOfData();
158 }
159 };
160
161 try {
162 empty.peek();
163 fail("peek() should throw NoSuchElementException at end");
164 } catch (NoSuchElementException expected) {
165 }
166
167 try {
168 empty.peek();
169 fail("peek() should continue to throw NoSuchElementException at end");
170 } catch (NoSuchElementException expected) {
171 }
172 }
173
174 public void testSneakyThrow() throws Exception {
175 Iterator<Integer> iter = new AbstractIterator<Integer>() {
176 boolean haveBeenCalled;
177 @Override public Integer computeNext() {
178 if (haveBeenCalled) {
179 fail("Should not have been called again");
180 } else {
181 haveBeenCalled = true;
182 sneakyThrow(new SomeCheckedException());
183 }
184 return null;
185 }
186 };
187
188
189 try {
190 iter.hasNext();
191 fail("No exception thrown");
192 } catch (Exception e) {
193 if (!(e instanceof SomeCheckedException)) {
194 throw e;
195 }
196 }
197
198
199 try {
200 iter.hasNext();
201 fail("No exception thrown");
202 } catch (IllegalStateException expected) {
203 }
204 }
205
206 public void testException() {
207 final SomeUncheckedException exception = new SomeUncheckedException();
208 Iterator<Integer> iter = new AbstractIterator<Integer>() {
209 @Override public Integer computeNext() {
210 throw exception;
211 }
212 };
213
214
215 try {
216 iter.hasNext();
217 fail("No exception thrown");
218 } catch (SomeUncheckedException e) {
219 assertSame(exception, e);
220 }
221 }
222
223 public void testExceptionAfterEndOfData() {
224 Iterator<Integer> iter = new AbstractIterator<Integer>() {
225 @Override public Integer computeNext() {
226 endOfData();
227 throw new SomeUncheckedException();
228 }
229 };
230 try {
231 iter.hasNext();
232 fail("No exception thrown");
233 } catch (SomeUncheckedException expected) {
234 }
235 }
236
237 public void testCantRemove() {
238 Iterator<Integer> iter = new AbstractIterator<Integer>() {
239 boolean haveBeenCalled;
240 @Override public Integer computeNext() {
241 if (haveBeenCalled) {
242 endOfData();
243 }
244 haveBeenCalled = true;
245 return 0;
246 }
247 };
248
249 assertEquals(0, (int) iter.next());
250
251 try {
252 iter.remove();
253 fail("No exception thrown");
254 } catch (UnsupportedOperationException expected) {
255 }
256 }
257
258 public void testReentrantHasNext() {
259 Iterator<Integer> iter = new AbstractIterator<Integer>() {
260 @Override protected Integer computeNext() {
261 hasNext();
262 return null;
263 }
264 };
265 try {
266 iter.hasNext();
267 fail();
268 } catch (IllegalStateException expected) {
269 }
270 }
271
272
273
274
275
276
277
278
279 private static void sneakyThrow(Throwable t) {
280 class SneakyThrower<T extends Throwable> {
281 @SuppressWarnings("unchecked")
282 void throwIt(Throwable t) throws T {
283 throw (T) t;
284 }
285 }
286 new SneakyThrower<Error>().throwIt(t);
287 }
288
289 private static class SomeCheckedException extends Exception {
290 }
291
292 private static class SomeUncheckedException extends RuntimeException {
293 }
294 }